package club.hicode.daydayup.retry;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.apache.bcel.generic.RET;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.RecoveryCallback;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryPolicy;
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.backoff.BackOffPolicy;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.AlwaysRetryPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.Random;

/**
 * Spring-Retry 的学习和测试代码
 *
 * @author Liu Chunfu
 * @date 2018-04-16 下午7:39
 **/
@Slf4j
@Service
public class SpringTemplateRetry {

    private RetryTemplate retryTemplate = new RetryTemplate();

    private RetryPolicy retryPolicy = new AlwaysRetryPolicy();

    private BackOffPolicy backOffPolicy = new FixedBackOffPolicy();


    //@PostConstruct
    //public void testRetry() throws Throwable {
    //    retryTemplate.setRetryPolicy(retryPolicy);
    //    retryTemplate.setBackOffPolicy();
    //    retryTemplate.setBackOffPolicy(backOffPolicy);
    //
    //    retryTemplate.execute(new RetryCallback<Boolean>() {
    //
    //        @Override
    //        public Boolean doWithRetry(RetryContext context) throws Throwable {
    //            return null;
    //        }
    //    });
    //}

    public static Boolean vpmsRetryCoupon(final String userId) {
        // 构建重试模板实例
        RetryTemplate retryTemplate = new RetryTemplate();
        // 设置重试策略，主要设置重试次数
        SimpleRetryPolicy policy = new SimpleRetryPolicy(10, Collections.singletonMap(Exception.class, true));

        //一直 try,不管如何一直 try
        //AlwaysRetryPolicy policy=new AlwaysRetryPolicy();

        // 设置重试回退操作策略，主要设置重试间隔时间
        FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
        fixedBackOffPolicy.setBackOffPeriod(100);

        retryTemplate.setRetryPolicy(policy);
        retryTemplate.setBackOffPolicy(fixedBackOffPolicy);

        // 通过RetryCallback 重试回调实例包装正常逻辑逻辑，第一次执行和重试执行执行的都是这段逻辑
        final RetryCallback<Object, Exception> retryCallback = new RetryCallback<Object, Exception>() {
            //RetryContext 重试操作上下文约定，统一spring-try包装
            @Override
            public Object doWithRetry(RetryContext context) throws Exception {
                boolean result = pushCouponByVpmsaa(userId);
                if (!result) {
                    //这个点特别注意，重试的根源通过Exception返回
                    throw new RuntimeException();
                }
                return true;
            }
        };

        // 通过RecoveryCallback 重试流程正常结束或者达到重试上限后的退出恢复操作实例
        final RecoveryCallback<Object> recoveryCallback = new RecoveryCallback<Object>() {
            @Override
            public Object recover(RetryContext context) throws Exception {
                log.info("正在重试发券::::::::::::" + userId);
                return null;
            }
        };
        try {
            // 由retryTemplate 执行execute方法开始逻辑执行
            retryTemplate.execute(retryCallback, recoveryCallback);
        } catch (Exception e) {
            log.info("发券错误异常========" + e.getMessage());
            e.printStackTrace();
        }
        return true;
    }

    public static void main(String[] args) {
        vpmsRetryCoupon("43333");
    }


    public static Boolean pushCouponByVpmsaa(String userId) {
        Random random = new Random();
        int a = random.nextInt(10);
        System.out.println("a是" + a);
        if (a == 8) {
            return true;
        } else {
            return false;
        }
    }
}
